class EventBus {
  events: Record<string, Set<(data: any) => void>> = {}

  on(eventName: string, cb: (data: any) => void) {
    ;(this.events[eventName] ??= new Set()).add(cb)
  }

  emit(eventName: string, data?: any) {
    this.events[eventName]?.forEach(cb => cb(data))
  }

  off(eventName: string, cb: (data: any) => void) {
    this.events[eventName]?.delete(cb)
  }

  once(eventName: string, cb: (data: any) => void) {
    const onceCb = (data: any) => {
      cb(data)
      this.off(eventName, onceCb)
    }
    this.on(eventName, onceCb)
  }
}

export const bus = new EventBus()
